<template>
    <div class="threejs-scene-container" :style="{ cursor: 'url(' + cursorURL + '), default' }">
          <audio class="clickSound" preload="auto" style="display: none;">
                <source src="/audio/Duang.mp3" type="audio/mpeg">
          </audio>
          <audio class="kmsSound" preload="auto" style="display: none;">
                <source src="/audio/kemusan.mp3" type="audio/mpeg">
          </audio>
          <div class="bt-container" v-show="showQuit" style="position: fixed;bottom: 15%;left: 48%;">
                <button class="light-1" @click="quit" style="font-size: 25px;user-select: none;">离开</button>
          </div>
          <img :src="playIcon" @click="changePlay" v-show="showPlay" style="position: fixed;right: 10%;bottom: 10%;">
    </div>
</template>

<script>
import { MeshPhysicalMaterial, MeshStandardMaterial, SRGBColorSpace, SceneManager, SceneParams, createLabel, generateBox, instantiateGroup } from '@/components/common/scenemanager';
import ErrorEmote from '@/components/specialeffects/ErrorEmote.vue';
import JSZip from 'jszip';
import { h, render } from 'vue';

export default {
    name: "ThreejsScene",
    components: {},
    data() {
          return {
                cursorURL: "/ico/cursor_22.ico",
                cursorPointer: "/ico/cursor_22.ico",
                cursorHand: "/ico/m_cursor_hand_c.ico",
                playIcon: "/img/button/play_stop.png",
                playPlay: "/img/button/play_play.png",
                playStop: "/img/button/play_stop.png",
                isPlaying: true,//是否自动播放
                showPlay: false,//显示播放按钮
                showMenu: false,//显示人物菜单
                showQuit: false,//显示离开按钮
                lightIsON: true,//路灯:开/关
                boxIsON: true,//电箱:开/关
                isNight: false,//白天/晚上
                petals: null,//花瓣
                iskicking: false,//踢树动画中
                sceneManager: null,
                hasError: false,//加载是否有报错
          }
    },
    computed: {},
    methods: {
          playKemusan() {
                const sound = this.$el.parentElement.querySelector(".kmsSound");
                sound.currentTime = 18;
                sound.play();
          },
          stopKemusan() {
                const sound = this.$el.parentElement.querySelector(".kmsSound");
                sound.pause();
          },
          changePlay() {
                if (this.isPlaying) {
                      this.isPlaying = false;
                      this.playIcon = this.playPlay;
                      this.sceneManager.disableAutoRotate();
                } else {
                      this.isPlaying = true;
                      this.playIcon = this.playStop;
                      this.sceneManager.enableAutoRotate();
                }
          },
          //显示屏2
          openScreen2() {
                window.open("/StyleView", "_blank");
          },
          //离开
          quit() {
                this.sceneManager.changeSceneInfo(0);
                this.showQuit = false;
                this.showPlay = true;
          },
          //选中月亮
          clickMoon() {
                if (this.isNight) {
                      this.isNight = false;
                      this.sceneManager.setEnv(0, "sky_day");
                      this.sceneManager.setEnv(1, "sky_day");
                } else {
                      this.isNight = true;
                      this.sceneManager.setEnv(0, "sky_night");
                      this.sceneManager.setEnv(1, "sky_night");
                }
          },
          //选中一楼大门
          clickDoor1() {
                this.sceneManager.changeSceneInfo(1);
                this.showQuit = true;
                this.showPlay = false;
          },
          //选中二楼大门
          clickDoor2() {

          },
          //选中电箱
          clickBox() {
                if (this.boxIsON) {
                      this.boxIsON = false;
                      this.sceneManager.changeModelMaterial(0, "立方体", "light_off");
                      this.sceneManager.changeModelMaterial(0, "windows_door", "glass");
                      this.sceneManager.changeModelMaterial(0, "windows_low", "glass");
                      this.sceneManager.changeModelMaterial(0, "windows_up", "glass");
                      this.sceneManager.changeModelMaterial(0, "windows_up_door1", "glass");
                      this.sceneManager.changeModelMaterial(0, "windows_up_door2", "glass");
                      this.sceneManager.changeModelMaterial(0, "word", "word_off");
                } else {
                      this.boxIsON = true;
                      if (this.lightIsON) {
                            this.sceneManager.changeModelMaterial(0, "立方体", "light_on");
                      }
                      this.sceneManager.changeModelMaterial(0, "windows_door", "window");
                      this.sceneManager.changeModelMaterial(0, "windows_low", "window");
                      this.sceneManager.changeModelMaterial(0, "windows_up", "window");
                      this.sceneManager.changeModelMaterial(0, "windows_up_door1", "window");
                      this.sceneManager.changeModelMaterial(0, "windows_up_door2", "window");
                      this.sceneManager.changeModelMaterial(0, "word", "word_on");
                }
          },
          //选中樱花树
          clickTree() {
                if (this.iskicking) {
                      return;
                }
                this.iskicking = true;

                const tree = this.sceneManager.findObjectByName("tree_act");
                this.sceneManager.playAnimation("kick_tree", tree.parent, 1.0, false);

                //花瓣飘落
                const petal = instantiateGroup(this.petals);
                this.sceneManager.addModelToScene(0, petal);
                this.sceneManager.playAnimation("flower_down", petal, 1.0, false);
          },
          //选中路灯
          clickLight() {
                if (!this.boxIsON) {
                      return;
                }
                if (this.lightIsON) {
                      this.lightIsON = false;
                      this.sceneManager.changeModelMaterial(0, "立方体", "light_off");
                } else {
                      this.lightIsON = true;
                      this.sceneManager.changeModelMaterial(0, "立方体", "light_on");
                }
          },
          //选中人物
          clickMan() {
                if (this.showMenu) {
                      this.showMenu = false;
                      const kemusan = this.sceneManager.findObjectByName("kemusan");
                      kemusan.visible = false;
                      this.sceneManager.deleteCanPicked(0, "kemusan");

                      const jiedan = this.sceneManager.findObjectByName("jiedan");
                      jiedan.visible = false;
                      this.sceneManager.deleteCanPicked(0, "jiedan");
                } else {
                      this.showMenu = true;
                      const kemusan = this.sceneManager.findObjectByName("kemusan");
                      kemusan.visible = true;
                      this.sceneManager.addCanPicked(0, kemusan, "kemusan", false);

                      const jiedan = this.sceneManager.findObjectByName("jiedan");
                      jiedan.visible = true;
                      this.sceneManager.addCanPicked(0, jiedan, "jiedan", false);
                }
          },
          //选中科目三
          clickKemusan() {
                if (!this.showMenu) {
                      return;
                }
                if (this.isPlaying) {
                      this.changePlay();
                }
                this.showPlay = false;
                this.playKemusan();
                this.showMenu = false;
                const kemusan = this.sceneManager.findObjectByName("kemusan");
                kemusan.visible = false;
                this.sceneManager.deleteCanPicked(0, "kemusan");
                const man = this.sceneManager.findObjectByName("body.001");
                this.sceneManager.crossFadeToAnimation("idel", "kemusan", man, 1.0, false);

                const jiedan = this.sceneManager.findObjectByName("jiedan");
                jiedan.visible = false;
                this.sceneManager.deleteCanPicked(0, "jiedan");
          },
          //接单
          jiedan() {
                if (!this.showMenu) {
                      return;
                }
                this.showMenu = false;
                const kemusan = this.sceneManager.findObjectByName("kemusan");
                kemusan.visible = false;
                this.sceneManager.deleteCanPicked(0, "kemusan");

                const jiedan = this.sceneManager.findObjectByName("jiedan");
                jiedan.visible = false;
                this.sceneManager.deleteCanPicked(0, "jiedan");
          },
          //手指点击
          clickHand(event) {
                let isLeftMB = false;
                let isRightMB = false;
                if ("which" in event) {
                      isRightMB = event.which == 3;
                      isLeftMB = event.which == 1;
                }
                else if ("button" in event) {
                      isRightMB = event.button == 2;
                      isLeftMB = event.button == 0;
                }
                if (!isLeftMB) {//不是左键被按下
                      return;
                }

                //播放点击音效
                const sound = this.$el.parentElement.querySelector(".clickSound");
                sound.play();

                const picked = this.sceneManager.getPicked();
                if (!picked) {//未选中物体
                      return;
                }

                switch (picked.name) {
                      case "moon":
                            this.clickMoon();
                            break;
                      case "dianxiang":
                            this.clickBox();
                            break;
                      case "立方体_1":
                            this.clickLight();
                            break;
                      case "tree":
                            this.clickTree();
                            break;
                      case "man":
                            this.clickMan();
                            break;
                      case "kemusan":
                            this.clickKemusan();
                            break;
                      case "jiedan":
                            this.jiedan();
                            break;
                      case "windows_door":
                            this.clickDoor1();
                            break;
                      case "立方体010_1":
                            this.openScreen2();
                            break;
                      default:
                            break;
                }
          },
          //加载失败
          loadError(error) {
                console.error(error);
                this.hasError = true;
                const view = this.$el.parentElement.querySelector(".threejs-scene-container");
                const errorIns = h(ErrorEmote);
                render(errorIns, view);
          },
          //创建材质
          createMaterials() {
                //创建材质

                //招牌文字的材质
                this.sceneManager.addMaterial("word_on", {
                      color: 0xE7E7E7,
                      roughness: 0.5,
                      emissive: 0xFFF8AE,
                      emissiveIntensity: 2.0,
                }, MeshStandardMaterial);
                this.sceneManager.addMaterial("word_off", {
                      color: 0xFFFFFF,
                      roughness: 0.5,
                }, MeshStandardMaterial);

                //花的材质
                const flowerTX = this.sceneManager.txMap.get("/img/common/yinghua1.png");
                flowerTX.colorSpace = SRGBColorSpace;
                flowerTX.flipY = false;
                this.sceneManager.addMaterial("flower_act", {
                      color: 0xE7B3E1,
                      map: flowerTX,
                      roughness: 0.5,
                      transparent: true,
                      alphaTest: 0.02,
                }, MeshStandardMaterial);

                //花瓣的材质
                const petalTX = this.sceneManager.txMap.get("/img/specialeffects/flower2.png");
                petalTX.colorSpace = SRGBColorSpace;
                petalTX.flipY = false;
                this.sceneManager.addMaterial("petal_act", {
                      color: 0xE7B3E1,
                      map: petalTX,
                      roughness: 0.5,
                      transparent: true,
                      alphaTest: 0.02,
                }, MeshStandardMaterial);

                //树的材质
                this.sceneManager.addMaterial("tree_act", {
                      color: 0xA8755A,
                      roughness: 1.0,
                }, MeshStandardMaterial);

                //路灯的材质
                this.sceneManager.addMaterial("light_on", {
                      color: 0x5F5F5F,
                      roughness: 0.5,
                      emissive: 0xFFEF83,
                      emissiveIntensity: 20.0,
                }, MeshStandardMaterial);
                this.sceneManager.addMaterial("light_off", {
                      color: 0xFFFFFF,
                      roughness: 0.5,
                }, MeshStandardMaterial);

                //窗户的材质
                this.sceneManager.addMaterial("window", {
                      emissive: 0xFFFF66,
                      emissiveIntensity: 3.0,
                }, MeshStandardMaterial);

                //透明玻璃材质
                this.sceneManager.addMaterial("glass", {
                      opacity: 0.2,
                      transmission: 0.9,
                      transparent: true,
                }, MeshPhysicalMaterial);
          },
          //可选物体
          initCanPicked() {
                //可被选中物体名称
                const canSelected1 = new Map();
                canSelected1.set("windows_door", true);
                canSelected1.set("windows_up_door1", true);
                canSelected1.set("windows_up_door2", true);
                canSelected1.set("tree", false);
                canSelected1.set("dianxiang", true);
                canSelected1.set("moon", false);
                canSelected1.set("立方体_1", false);
                canSelected1.set("man", false);

                const canSelected2 = new Map();
                canSelected2.set("立方体010_1", false);

                this.sceneManager.setCanPickedMap(0, canSelected1);
                this.sceneManager.setCanPickedMap(1, canSelected2);
          },
          //启用阴影物体
          initShadow() {
                const shadowOn = new Array();
                shadowOn.push("room");
                shadowOn.push("wuding");
                shadowOn.push("word");
                shadowOn.push("rail");
                shadowOn.push("tile");
                shadowOn.push("flower_act");
                shadowOn.push("rail");
                shadowOn.push("ground");
                shadowOn.push("rocks");
                shadowOn.push("yizi");
                shadowOn.push("frame");
                shadowOn.push("grass");
                shadowOn.push("grassrct");
                shadowOn.push("tree_act");
                shadowOn.push("立方体");
                shadowOn.push("立方体_1");
                shadowOn.push("立方体014");

                this.sceneManager.setShadowList(shadowOn);
          },
          _fetchZip(path) {
                return fetch(path).then(response => {
                      if (response.status === 200 || response.status === 0) {
                            return Promise.resolve(response.blob());
                      } else {
                            return Promise.reject(new Error(response.statusText));
                      }
                }).then(JSZip.loadAsync, this.loadError);
          },
          //加载模型
          loadModel() {
                this.sceneManager.loadHDRAndTX([], [
                      "/img/common/yinghua1.png",
                      "/img/specialeffects/flower2.png",
                ], () => {
                      this.createMaterials();
                      this.sceneManager.changeModelMaterial(0, "flower_act", "flower_act");
                      this.sceneManager.changeModelMaterial(0, "tree_act", "tree_act");
                      if (this.petals) {
                            this.sceneManager.addMaterialForModel(this.petals);
                      }
                }, undefined, this.loadError);

                this._fetchZip("/model/skyhdr.zip").then(zip => {
                      zip.file("sky_day.hdr").async("arraybuffer").then(data => {
                            this.sceneManager.createHDR("sky_day", data, () => {
                                  this.sceneManager.setEnv(0, "sky_day");
                                  this.sceneManager.setEnv(1, "sky_day");
                            }, undefined, this.loadError);
                      });
                      zip.file("sky_night.hdr").async("arraybuffer").then(data => {
                            this.sceneManager.createHDR("sky_night", data, undefined, undefined, this.loadError);
                      });
                }, this.loadError);

                this._fetchZip("/model/tree.zip").then(zip => {
                      zip.file("tree.glb").async("arraybuffer").then(data => {
                            this.sceneManager.loadModelByData(data, this.addTreeToScene, this.loadError);
                      });
                }, this.loadError);

                this._fetchZip("/model/Dracohouse.zip").then(zip => {
                      zip.file("Dracohouse.gltf").async("arraybuffer").then(data => {
                            this.sceneManager.loadModelByData(data, this.addModelToFirstScene, this.loadError);
                      });
                }, this.loadError);

                this._fetchZip("/model/Dracoland.zip").then(zip => {
                      zip.file("Dracoland.gltf").async("arraybuffer").then(data => {
                            this.sceneManager.loadModelByData(data, this.addLandToScene, this.loadError);
                      });
                }, this.loadError);

                this._fetchZip("/model/Dracopetal.zip").then(zip => {
                      zip.file("Dracopetal.gltf").async("arraybuffer").then(data => {
                            this.sceneManager.loadModelByData(data, this.savePetal, this.loadError);
                      });
                }, this.loadError);

                this._fetchZip("/model/Dracopgman.zip").then(zip => {
                      zip.file("Dracopgman.gltf").async("arraybuffer").then(data => {
                            this.sceneManager.loadModelByData(data, this.addManToScene, this.loadError);
                      });
                }, this.loadError);

                this._fetchZip("/model/Dracopgroom.zip").then(zip => {
                      zip.file("Dracopgroom.gltf").async("arraybuffer").then(data => {
                            this.sceneManager.loadModelByData(data, this.addModelToSceondScene, this.loadError);
                      });
                }, this.loadError);

                this.draw();
          },
          //保存花瓣
          savePetal(models) {
                this.sceneManager.addMaterialForModel(models.scene);
                this.petals = models.scene
                for (const ani of models.animations) {
                      this.sceneManager.addAnimationToScene(ani);
                }
          },
          //场景添加树
          addTreeToScene(models) {
                //为提高射线拾取效率在树的位置放一个不可见的长方体作为射线拾取的对象
                const cube = generateBox({
                      x: 9.5,
                      y: 3.3,
                      z: -12,
                }, {
                      x: 1,
                      y: 7,
                      z: 1,
                }, false);
                cube.name = "tree";
                models.scene.add(cube);
                this.addModelToFirstScene(models);

                this.sceneManager.changeModelMaterial(0, "flower_act", "flower_act");
                this.sceneManager.changeModelMaterial(0, "tree_act", "tree_act");
          },
          //隐藏骨骼
          hiddenSkeleton(bone) {
                bone.visible = false;
                for (const b of bone.children) {
                      this.hiddenSkeleton(b);
                }
          },

          //场景添加人物
          addManToScene(models) {
                this.hiddenSkeleton(models.scene.children[0].children[1]);
                this.hiddenSkeleton(models.scene.children[0].children[2]);

                //为提高射线拾取效率在人的位置放一个不可见的长方体作为射线拾取的对象
                const cube = generateBox({
                      x: 0,
                      y: 1,
                      z: 0,
                }, {
                      x: 1,
                      y: 1,
                      z: 1,
                }, false);
                cube.name = "man";
                models.scene.add(cube);

                const label1 = createLabel(["来一段科目三"]);
                label1.name = "kemusan";
                label1.position.y = 2.5;
                label1.visible = false;
                models.scene.add(label1);

                const words = [
                      "生活不易在线卖艺",
                      "全栈开发Java或go",
                      "网页设计在线接单",
                      "个人开发能力有限",
                      "如有意向窗口留言",
                      "三日未回默认不干",
                      "你提需求我来报价",
                      "合适就干不和就散",
                      "如有冒犯还请见谅",
                      "随缘接单好聚好散",
                ];
                const label2 = createLabel(words);
                label2.name = "jiedan";
                label2.position.y = 8.5;
                label2.visible = false;
                models.scene.add(label2);

                //设置位置
                models.scene.translateX(-3);
                models.scene.translateY(-0.35);
                models.scene.translateZ(14);
                this.addModelToFirstScene(models);

                //人物默认动画
                const man = this.sceneManager.findObjectByName("body.001");
                this.sceneManager.playAnimation("idel", man, 1.0, true);
          },

          //场景添加陆地
          addLandToScene(models) {
                this.addModelToFirstScene(models);

                //播放自转动画
                const land = this.sceneManager.findObjectByName("球体001");
                this.sceneManager.playAnimation("rotation", land, 0.2, true);
          },
          //第一个场景添加模型
          addModelToFirstScene(models) {
                this.sceneManager.addMaterialForModel(models.scene);
                this.sceneManager.addModelToScene(0, models.scene);

                for (const ani of models.animations) {
                      this.sceneManager.addAnimationToScene(ani);
                }
          },
          //第二个场景添加模型
          addModelToSceondScene(models) {
                models.scene.name = "inroom";
                this.sceneManager.addMaterialForModel(models.scene);
                this.sceneManager.addModelToScene(1, models.scene);

                for (const ani of models.animations) {
                      this.sceneManager.addAnimationToScene(ani);
                }
          },
          //开始渲染
          draw() {
                if (this.hasError) {
                      return;
                }

                const view = this.$el.parentElement.querySelector(".threejs-scene-container");
                view.appendChild(this.sceneManager.getRenderDom());

                this.sceneManager.enableRaycaster();

                this.sceneManager.start();

                this.showPlay = true;

                view.addEventListener("mouseup", this.clickHand);

                const finishedFun = function (e) {
                      if (e.action._clip.name === "flower_down") {
                            this.sceneManager.release(e.action._localRoot);
                      }
                      if (e.action._clip.name === "kick_tree") {
                            this.iskicking = false;
                      }
                      if (e.action._clip.name === "kemusan") {
                            this.showPlay = true;
                            this.stopKemusan();
                            const man = this.sceneManager.findObjectByName("body.001");
                            this.sceneManager.crossFadeToAnimation("kemusan", "idel", man, 1.0, true);
                      }
                }
                this.sceneManager.registeAnimationFinishEvent(undefined, finishedFun.bind(this));
          },
          pick() {
                const envTX = this.sceneManager.txMap.get("sky_day");
                if (envTX) {
                      envTX.offset.x += 1;
                }
                const picked = this.sceneManager.getPicked();
                if (picked) {//拾取物体时禁用自动旋转
                      this.cursorURL = this.cursorHand;
                      this.sceneManager.disableAutoRotate();
                } else {
                      this.cursorURL = this.cursorPointer;
                      if (this.isPlaying && this.sceneManager.currentSceneIndex === 0) {
                            this.sceneManager.enableAutoRotate();
                      } else {//停止播放时禁用自动旋转
                            this.sceneManager.disableAutoRotate();
                      }
                }
          },

          resize() {
                const view = this.$el.parentElement.querySelector(".threejs-scene-container");
                this.sceneManager.resize(view.offsetWidth, view.offsetHeight);
          },

          //第一个场景参数
          createFirstSceneParams() {
                const params = new SceneParams();
                params.cameraParams.fov = 60;
                params.cameraParams.near = 0.1;
                params.cameraParams.far = 1000;
                params.cameraParams.position.x = 10;
                params.cameraParams.position.y = 5;
                params.cameraParams.position.z = 30;

                params.rendererParams.shadowenabled = true;

                params.drctLightParams.color = 0x798EAA;
                params.drctLightParams.Intensity = 5;
                params.drctLightParams.castShadow = true;
                params.drctLightParams.position.x = -31;
                params.drctLightParams.position.y = 17;
                params.drctLightParams.position.z = 24;
                params.drctLightParams.TargetPosition.x = -23;
                params.drctLightParams.TargetPosition.y = 11;
                params.drctLightParams.TargetPosition.z = 22;
                params.drctLightParams.shadowCamera.left = -40;
                params.drctLightParams.shadowCamera.right = 40;
                params.drctLightParams.shadowCamera.top = 20;
                params.drctLightParams.shadowCamera.bottom = -20;
                params.drctLightParams.shadowCamera.width = 1024;
                params.drctLightParams.shadowCamera.height = 1024;

                params.controlsParams.enablePan = false;
                params.controlsParams.enableZoom = false;
                params.controlsParams.enableRotate = true;
                params.controlsParams.enableDamping = true;
                params.controlsParams.autoRotate = true;
                params.controlsParams.autoRotateSpeed = 1.0;

                params.composerParams.bloom.enabled = true;
                params.composerParams.bloom.strength = 0.2;
                params.composerParams.bloom.radius = 2.0;
                params.composerParams.bloom.threshold = 0.7;

                return params;
          },

          //第二个场景参数
          createSecondSceneParams() {
                const params = new SceneParams();

                params.cameraParams.fov = 60;
                params.cameraParams.near = 0.1;
                params.cameraParams.far = 1000;
                params.cameraParams.position.x = 0.2;
                params.cameraParams.position.y = 2.5;
                params.cameraParams.position.z = 1.5;
                params.cameraParams.target.x = 0.19;
                params.cameraParams.target.y = 2.72;
                params.cameraParams.target.z = -2.87;

                params.rendererParams.shadowenabled = false;

                params.drctLightParams.color = 0x798EAA;
                params.drctLightParams.Intensity = 5;
                params.drctLightParams.castShadow = false;
                params.drctLightParams.position.x = -31;
                params.drctLightParams.position.y = 17;
                params.drctLightParams.position.z = 24;
                params.drctLightParams.TargetPosition.x = -23;
                params.drctLightParams.TargetPosition.y = 11;
                params.drctLightParams.TargetPosition.z = 22;

                params.controlsParams.enablePan = false;
                params.controlsParams.enableZoom = false;
                params.controlsParams.angle.maxAzimuthAngle = Math.PI / 18;
                params.controlsParams.angle.minAzimuthAngle = -Math.PI / 18;
                params.controlsParams.angle.maxPolarAngle = Math.PI / 1.75;
                params.controlsParams.angle.minPolarAngle = Math.PI / 2;

                params.composerParams.bloom.enabled = false;

                return params;
          },
    },
    mounted() {
          const view = this.$el.parentElement.querySelector(".threejs-scene-container");
          this.sceneManager = new SceneManager(view.offsetWidth, view.offsetHeight, true);
          this.sceneManager.addScene(this.createFirstSceneParams(), this.pick);
          this.sceneManager.addScene(this.createSecondSceneParams(), this.pick);

          this.initCanPicked();
          this.initShadow();
          this.loadModel();

          window.addEventListener('resize', this.resize);
    },
    beforeUnmount() {
          const view = this.$el.parentElement.querySelector(".threejs-scene-container");
          view.removeEventListener("mouseup", this.clickHand);
          window.removeEventListener('resize', this.resize);
          this.sceneManager.destroy();
    },
}
</script>

<style scoped>
@import url('@/assets/css/button/light-1.css');

.threejs-scene-container {
    width: 100vw;
    height: 100vh;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
}
</style>